perm filename TAK.FAI[TIM,LSP] blob
sn#629783 filedate 1981-12-15 generic text, type C, neo UTF8
COMMENT ⊗ VALID 00002 PAGES
C REC PAGE DESCRIPTION
C00001 00001
C00002 00002 Martin:
C00010 ENDMK
C⊗;
Martin:
Here is the pdp-10 and s-1 code for TAK. I commented the
assembly language one a bit. Originally it was in LAP so that I
could use the same timer for this as for all of my other Lisp
benchmarking, so there could be some transcription errors.
This is very much bummed as you can see. I use the address calculation
hardware to do all my arithmetic and comparisons. I don't check for
stack overflow or underflow, I've transformed the program by folding in
the first arm of the conditional, and I've chosen register conventions to
use DMOVE's everywhere.
Here is the source level equivalent of these optimizations:
(defun btak (x y z)
(prog ()
(cond ((not (< y x))
(return z)))
tak2
(let ((a (let ((c (1- x)))
(cond ((not (< y c)) z)
(t (btak2 c y z)))))
(b (let ((c (1- y)))
(cond ((not (< z c)) x)
(t (btak2 c z x)))))
(c (let ((c (1- z)))
(cond ((not (< x c)) y)
(t (btak2 c x y))))))
(cond ((not (< b a)) (return c))
(t (setq x a
y b
z c)
(go tak2))))))
(defun btak2 (x y z)
(prog ()
tak2
(let ((a (let ((c (1- x)))
(cond ((not (< y c)) z)
(t (btak2 c y z)))))
(b (let ((c (1- y)))
(cond ((not (< z c)) x)
(t (btak2 c z x)))))
(c (let ((c (1- z)))
(cond ((not (< x c)) y)
(t (btak2 c x y))))))
(cond ((not (< b a)) (return c))
(t (setq x a
y b
z c)
(go tak2))))))
(defun timit ()
((lambda (t1 x gt)
(btak 18. 12. 6.)
(setq t1 (- (runtime) t1))
(setq gt (- (status gctime) gt))
(print (list 'runtime
(QUOTIENT (FLOAT (- t1 gt))
1000000.)))
(print (list 'gctime
(quotient (float gt) 1000000.))))
(runtime) ()(status gctime)))
;;; P and FXP are stacks that are guaranteed large enough.
;;; a,b,c are general registers for arguments; c is the result
;;; register. P is the control stack, fxp the temporary stack.
;;; called via a pushj p,tak1
tak1 caig a,(b) ;x < y quit
popj p,
tak2 add fxp,[5,,5] ;allocate 5 slots. 3 for args, 2 for temporaries
dmovem a,-2(fxp) ;move a,b,c onto the stack. add is used to push
movem c.(fxp) ;empty space, and the assumption of a large enough
;stack is used here. PUSH, ADJSP both do bounds
;checking. DMOVEM saves an instruction fetch and a
;decode.
movei a,-1(a) ;a←a-1 using the address hardware. Assumption
;is that 18 bit, non-negative arithmetic is going on
caile a,(b) ;early quit? c already contains the right result.
;this early quit just unwinds the first arm of
;the conditional. Tak2 is the entry after that arm
pushj p,tak2 ;no go on
movem c,-4(fxp) ;save result on fxp
dmove a,-1(fxp) ;get y,z
move c,-2(fxp) ;and x
movei a,-1(a) ;sub1
caile a,(b) ;early quit
pushj p,tak2
movem c,-3(fxp) ;stash result
move a,(fxp) ;z
dmove b,-2(fxp) ;x,y
movei a,-1(a) ;sub1
caile a,(b)
pushj p,tak2
dmove a,-4(fxp) ;get first 2 results, the last already in c
;notice how the choice of c as the results
;register allowed us to hack the dmove's here
sub fxp,[5,,5] ;flush temporary space
caig a,(b) ;early quit on tail recursion?
popj p, ;qed
jrst tak2 ;tail recursion
Here's the actual s-1 code I used. The same bums are right for this
machine too. This is the Mark I, not the Mark IIA.
title tak
DEFINE OUTSTR "(<{B}>)" STRING
JSR #⊂STRING⊃,STROUT
TERMIN
pc←%3
a←%10
b←%11
c←%12
fxp←%34
sp←%36
go: wspid #sp
mov.d.d sp,[pdl ↔ pdlend]
mov.d.d fxp,[fxpdl ↔ fxpdlend]
timer time1
movms.3 a,[18. ↔ 12. ↔ 6]
jsr tak1
timer time2
outstr [asciz /Answer = /]
mov a,c
jsr decout
outstr [asciz / in /]
sub rta,time2+4,time1+4
quo rta,#10. ;convert to microseconds
mov a,rta
jsr decout
outstr [asciz / microseconds.
/]
halt .
tak1: skp.gtr a,b
retsr pc,(sp)
tak2: add fxp,#5*4
movms.3 -3(fxp),a
djmp.leq a
jsr tak2
mov -5(fxp),c
mov.d.d a,-2(fxp)
mov c,-3(fxp)
djmp.leq a
jsr tak2
mov -4(fxp),c
mov a,-1(fxp)
mov.d.d b,-3(fxp)
djmp.leq a
jsr tak2
mov.d.d a,-5(fxp)
sub fxp,#5*4
jmp.gtr a,tak2
retsr pc,(sp)
decout: div a,#10.
jmpz.eql a,decou1
jsr b,decout
decou1: add b,?"0"
outchr b
retsr b,(sp)
STROUT: ALLOC.2 A,#2*4
MOV A,-4(SP) ;GET BYTE ADDRESS OF STRING
STROU1: MOV.S.Q B,(A) ;GET NEXT BYTE
JMPZ.EQL B,STROUD
OUTCHR B
IJMPA A,STROU1
STROUD: MOVMS.2 A,-2(SP)
RETSR PC,-2(SP)
time1: block 2
time2: block 2
pdl: block 5000
pdlend:
fxpdl: block 5000
fxpdlend:
end go